#!/usr/bin/perl

=head1 NAME

AFX::Rcmd - Remote Command Execution Script.

=head1 COPYRIGHT AND LICENSE

Copyright (C) 2010 Mikhail Volkov

This file is part of AuditFX.

    AuditFX is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    AuditFX is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with AuditFX.  If not, see <http://www.gnu.org/licenses/>.
=cut

##############################################################################
# Globals
#

use lib 'lib';
use strict;
use warnings;

use Getopt::Std;

use AFX::ACF;
use AFX::ASF;

## Try to use Process library
eval "use AFX::Process";
if ($@) {
    print "Failed loading AFX::Process library. Error: $@\n";
    die $@;
}

## Execute main script
rcmd();

##############################################################################
#
# rcmd()
#
# Command arguments expected are:
# - (-s) site_id     - Site id
# - (-u) units       - Unit's Identifiers
# - (-m) machines    - Machine's Identifiers
# - (-t) scenarios   - Scenario's Identifiers
# - (-l) login       - Login's Identifier
# - (-D)             - Debug mode
# - (-x)             - Noprompt mode

sub rcmd {

## Get options
    getopts( "xhDs:u:m:l:t:", \my %opts );

## Print rcmd usage message
    print rcmd_usage();

## Check if Help required
    if ( $opts{h} ) {

## Print audit help message
        print rcmd_help();
        
## Exit with status
        exit(0);
    }

## Open ACF
    my $acf = new AFX::ACF();

## Define variables for SITE_ID, UNITS, MACHINES
    my ( $site_id, @units, @machines, $login );

## Define Scenario
    my @scenarios = ('RCMD');

## Check is SITE_ID specified
    if ( $opts{s} ) {
        $site_id = uc( $opts{s} );
    }
    else {

## If Site Identifier not specified, default will be used
        $site_id = $acf->open_sitefile();
    }

## Print rcmd started message
    rcmd_started( $acf, $site_id );

## Print version message
    print $acf->message_title() . "\n\n";

## Check is UNITS specified
    if ( $opts{u} ) {
        @units = split( /,/, uc( $opts{u} ) );
    }

## Check is MACHINES specified
    if ( $opts{m} ) {
        @machines = split( /,/, uc( $opts{m} ) );
    }

## Check is SCENARIOS specified
    if ( $opts{t} ) {
        @scenarios = split( /,/, $opts{t} );
    }

## Check is Login specified
    if ( $opts{l} ) {
        $login =  $opts{l};
    }
    else {
## If Login Identifier not specified, default will be used
        $login = 'root';
    }

## Set default debug mode
    my $debug = 0;

## Check if Debug mode specified
    if ( $opts{D} ) {
        $debug = 1;
    }

## Set default noprompt mode
    my $noprompt = 0;

## Check if Noprompt mode specified
    if ( $opts{x} ) {
        $noprompt = 1;
    }

## Open ASF
    my $asf = new AFX::ASF( $acf, $site_id ) if $site_id;

## Exit with exception: ASF processing error
    if ( !$asf ) {

## Set Error status
        my $status = 1;

## Print Rcmd finished message
        rcmd_finished( $acf, $site_id, $status );

## Exit with status
        exit($status);
    }

## Update ASF using SMF
    $asf->parse_smf($noprompt);

## If Machines not specified
    if ( !@units and !@machines ) {

## Print no unit message
        message_no_unit($acf);

## Print units details
        $asf->show_units();

## Set Error status
        my $status = 1;

## Print rcmd finished message
        rcmd_finished( $acf, $site_id, $status );

## Exit with status
        exit($status);
    }

## Create Process
    my $process = new AFX::Process( $acf, $asf, 'rcmd' );

## If process wasn't created
    if ( !$process ) {

## Print process failed message
        $acf->message_failed_process();

## Set Error status
        my $status = 1;

## Print rcmd finished message
        rcmd_finished( $acf, $site_id, $status );

## Exit with status
        exit($status);
    }

## Add machine for processing
    $process->add_machine( \@units, \@machines );

## Set debug mode if specified
    $process->set_debug() if $debug;

## Set noprompt mode if specified
    $process->set_noprompt() if $noprompt;

## Set Error status
    my $status = 1;

## Execute Process
    if ( $process->proc_rcmd( $login, \@scenarios ) ) {

## Set status
        $status = 0;
    }

## Print rcmd finished message
    rcmd_finished( $acf, $site_id, $status );

## Exit with status
    exit($status);

} ## end sub rcmd

##############################################################################
#
# rcmd_help()
#
# Message: Rcmd help
#
# Return:
# - logged message

sub rcmd_help {

## Set message
    my $message .= "\nFlags:";
    $message .= "\n-s SITE_ID:
    Identifies a site to be audited. Unique Site Identifier should follow -s option as an argument. Unique Site Identifier should be obtained as name of SITE_ID.master file(s). If not specified, then default value configured while config.pl used.";
    $message .= "\n-u MACH: 
    Identifies units to be audited. Argument is comma separated list of units. Example: SDP,SLU,UPM,etc. For all units list see TEST.master inside of the site folder.";
    $message .= "\n-m MACH_ID:
    Identifies machines to be audited. Argument is comma separated list of machines. Example: SDP1,SDP2,SLU5,etc. Machines list depends on site configuration and SITE_ID.master file created to audit the site.";
    $message .= "\n-t SCENARIO:
    Identifies scenario contains commands. Scenarios list should be obtained from scenario folder.";
    $message .= "\n-l LOGIN:
    Identifies login under which commands to be executed.";
    $message .= "\n-D:
    Enables DEBUG mode";
    $message .= "\n-x:
    Enables noprompt mode\n";

## Return message
    return $message;

} ## end sub rcmd_help

##############################################################################
#
# rcmd_started()
#
# Message: Rcmd started
#
# Return:
# - logged message
#
# Arguments expected are:
# - acf        - ACF Object
# - site_id    - Site Id

sub rcmd_started {
    my ( $acf, $site_id ) = @_;

## Get time
    my $now = localtime;

## Set message
    my $message = "\n## Rcmd of $site_id started at $now ";
    $message .= "#" while ( length($message) < 70 );
    $message .= "\n";

## Return message
    return $acf->logging( $message, 1, 'audit' );

} ## end sub rcmd_started

##############################################################################
#
# rcmd_finished()
#
# Message: Rcmd finished
#
# Return:
# - logged message
#
# Arguments expected are:
# - acf        - ACF Object
# - site_id    - Site Id
# - status     - Process status

sub rcmd_finished {
    my ( $acf, $site_id, $status ) = @_;

## Get time
    my $now = localtime;

## Set message
    my $message = "\n## Rcmd of $site_id finished at $now ";
    $message .= "#" while ( length($message) < 70 );
    $message .= "\n";

## Show Status
    $message .= "STATUS=$status\n";

## If status is failed
    if ($status) {
        $message .=
          "INFO=Rcmd contains failed parameters or processing errors exist\n";
    }
    else {
        $message .= "INFO=No issues detected during rcmd execution\n";
    }

## Return message
    return $acf->logging( $message, 1, 'audit' );

} ## end sub rcmd_finished

##############################################################################
#
# rcmd_usage()
#
# Message: Rcmd usage
#
# Return:
# - logged message

sub rcmd_usage {

## Set message
    my $message =
"Usage: [perl] rcmd.pl [-s {SITE_ID}] [-u {MACH}] [-m {MACH_ID}] [-t {SCENARIO}] [-l {LOGIN}] [-D] [-x]";
    $message .= "\nHelp: [perl] rcmd.pl -h\n";

## Return message
    return $message;

} ## end sub rcmd_usage

##############################################################################
#
# message_no_unit()
#
# Message: No MACH specified.
#
# Return:
# - logged message
#
# Arguments expected are:
# - acf      - ACF Object

sub message_no_unit {
    my ($acf) = @_;

## Set message
    my $message = "Error: MACH or MACH_ID not specified.\n";
    $message .= "Please specify units or machines which will be audited.";

## Return message
    return $acf->logging( $message, 1, 'audit' );

} ## end sub message_no_unit
